/** iterator.d

//  Written in the D programming language 1.0

Authors:
	Wei Li (oldrev@gmail.com)

Copyright:	Copyright (C) 2007 Wei Li.
License:	BSD
*/

module dotmars.base.iterator;

enum TraversalCategory
{
    // 支持的操作 ++i i++ *i++
    Incrementable,

    //  ++i, a==b, a!=b
    SinglePass,

    // X u, ++i
    ForwardTraversal, //单向，迭代器可以复制也可以为未初始化

    // --r, r--
    Bidirectional, 

    // r += n, a+n,n+a r-=n, a-n, b-a; a[n], a[n]=v, a<b, a>b, a>=b, a<=b,
    RandomAccess
}


enum AccessCategory
{    
    Readable, // val = iterator.value
	Writable, // iterator.value = val
	ReadWrite, //both of above
    Swappable, //能交换两个迭代器指向的值 
	Lvalue     //左值，D中值类型没有显式引用，因此约定迭代器包含一个 .ptr 属性
}

////////////////////////////////////////////////////////////////////////////////
//等2.0的宏来替换这个函数

void assertCategory(Iter, TraversalCategory TC, AccessCategory AC)()
{
	static assert(Iter.TraversalTag >= TC);
	static assert(Iter.AccessTag >= AC);
}


////////////////////////////////////////////////////////////////////////////////

private struct InsertIteratorBase(Cont)
{
	public const TraversalCategory TraversalTag = TraversalCategory.Incrementable;
	public const AccessCategory AccessTag = AccessCategory.Writable;

	public alias Cont				ContainerType;
	public alias Cont.ValueType	ValueType;
	public alias Cont.PtrType		PtrType;
	public alias BackInsertIterator!(Cont) SelfType;

	private ContainerType	m_cont = null;

	public static SelfType opCall(ContainerType container)
	in {
		assert(container !is null);
	}
	body {
		SelfType iter;
		iter.m_cont = container;
		return iter;
	}

	public SelfType opPostInc() { //i++
		assert(m_cont !is null);
		return *this;
	}

	public SelfType opAddAssign(ptrdiff_t n) { // += {
		assert(m_cont !is null);
		return *this;
	}
}

struct BackInsertIterator(Cont)
{
	mixin InsertIteratorBase!(Cont);

	public void value(ValueType val) {
		assert(m_cont !is null);
		m_cont.addLast(val);
	}
}


struct FrontInsertIterator(Cont)
{
	mixin InsertIteratorBase!(Cont);

	public void value(ValueType val) {
		assert(m_cont !is null);
		m_cont.addFirst(val);
	}
}

////////////////////////////////////////////////////////////////////////////////



